<template>
  <div class="container" ref="container">
    <!-- 用于触发指针锁定的按钮 -->
    <button v-if="!isLocked" @click="lockPointer"
    >开始漫游</button>
  </div>
</template>

<script setup lang="ts">
import * as Three from 'three';
import { ref, onMounted } from 'vue';
import { GUI } from "three/examples/jsm/libs/lil-gui.module.min.js";
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';
import { PointerLockControls } from 'three/examples/jsm/controls/PointerLockControls';

const scene = new Three.Scene();
const camera = new Three.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 0.1;
const renderer = new Three.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
const container = ref(null);

const render = () => {
  renderer.render(scene, camera);
  requestAnimationFrame(render);
};

// 添加立方体
const geometry = new Three.BoxGeometry(10, 10, 10);
const arr = ['4_l', '4_r', '4_u', '4_d', '4_b', '4_f'];
const boxMaterials = [];
arr.forEach((item) => {
  let texture = new Three.TextureLoader().load(`./img/${item}.jpg`);
  if (item === '4_u' || item === '4_d') {
    texture.rotation = Math.PI;
    texture.center = new Three.Vector2(0.5, 0.5);
  }
  boxMaterials.push(new Three.MeshBasicMaterial({ map: texture }));
});
const cube = new Three.Mesh(geometry, boxMaterials);
cube.geometry.scale(1, 1, -1);
scene.add(cube);


let controls: PointerLockControls; //控制指针锁定
const isLocked = ref(false);

const keys = {//键盘按键状态
  forward: false,
  backward: false,
  left: false,
  right: false
};

const lockPointer = () => { //锁定指针
  controls.lock();
};

onMounted(() => {
  if (container.value) {
    controls = new PointerLockControls(camera, container.value);
    const orbitControls = new OrbitControls(camera, renderer.domElement);
    orbitControls.enableDamping = true;
    container.value.appendChild(renderer.domElement);
    // 监听指针锁定状态变化
    controls.addEventListener('lock', () => {
      isLocked.value = true;
    });
    controls.addEventListener('unlock', () => {
      isLocked.value = false;
    });
    const onKeyDown = (event: KeyboardEvent) => {
      switch (event.code) {
        case 'KeyW':
          keys.forward = true;
          break;
        case 'KeyS':
          keys.backward = true;
          break;
        case 'KeyA':
          keys.left = true;
          break;
        case 'KeyD':
          keys.right = true;
          break;
      }
    };

    const onKeyUp = (event: KeyboardEvent) => {
      switch (event.code) {
        case 'KeyW':
          keys.forward = false;
          break;
        case 'KeyS':
          keys.backward = false;
          break;
        case 'KeyA':
          keys.left = false;
          break;
        case 'KeyD':
          keys.right = false;
          break;
      }
    };

    window.addEventListener('keydown', onKeyDown);
    window.addEventListener('keyup', onKeyUp);

    const moveSpeed = 0.1;
    const animate = () => {//在指针锁定时根据按键状态计算相机的移动方向
      if (isLocked.value) {
        const direction = new Three.Vector3();
        if (keys.forward) {
          direction.z -= moveSpeed;
        }
        if (keys.backward) {
          direction.z += moveSpeed;
        }
        if (keys.left) {
          direction.x -= moveSpeed;
        }
        if (keys.right) {
          direction.x += moveSpeed;
        }
        // 根据相机方向移动
        direction.applyQuaternion(camera.quaternion);
        camera.position.add(direction);
      }
      requestAnimationFrame(animate);
    };

    animate();
    render();
  }
});
//监听窗口变化
window.addEventListener("resize", () => {
  renderer.setSize(window.innerWidth, window.innerHeight);
  camera.aspect = window.innerWidth / window.innerHeight;//更新相机宽高比
  camera.updateProjectionMatrix();//更新相机投影矩阵
});
let eventObj = {
  Fullscreen: function () {
    document.body.requestFullscreen();
    console.log("全屏");
  },
  ExitFullscreen: function () {
    document.exitFullscreen();
    console.log("退出全屏");
  },

};
const gui = new GUI();
gui.add(eventObj, "Fullscreen").name("全屏");
gui.add(eventObj, "ExitFullscreen").name("退出全屏");
</script>

<style scoped>
* {
  margin: 0;
  padding: 0;
}

.container {
  width: 100vw;
  height: 100vh;
  background-color: white;
  position: relative;
}

button {
  position: absolute;
  top: 20px;
  left: 20px;
  z-index: 1;
}
</style>